gesture: Handle GdkEventGrabBroken
authorCarlos Garnacho <carlosg@gnome.org>
Sat, 10 May 2014 18:46:47 +0000 (20:46 +0200)
committerCarlos Garnacho <carlosg@gnome.org>
Fri, 23 May 2014 17:54:30 +0000 (19:54 +0200)
That may happen separately from grab-notify, and also due to external
reasons, so ensure all sequences are cancelled if a grab is taken
in some GdkWindows that would obscure events on the controller.

gtk/gtkgesture.c
gtk/gtkgesturesingle.c

index e738e61c1ca5bc25176ba375a36e1023a755f0f0..9689f55a54dacc10a7204085f8425101d3907ab1 100644 (file)
@@ -478,6 +478,27 @@ _gtk_gesture_cancel_all (GtkGesture *gesture)
   _gtk_gesture_check_empty (gesture);
 }
 
+static gboolean
+gesture_within_window (GtkGesture *gesture,
+                       GdkWindow  *parent)
+{
+  GdkWindow *window;
+  GtkWidget *widget;
+
+  widget = gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture));
+  window = gtk_widget_get_window (widget);
+
+  while (window)
+    {
+      if (window == parent)
+        return TRUE;
+
+      window = gdk_window_get_effective_parent (window);
+    }
+
+  return FALSE;
+}
+
 static gboolean
 gtk_gesture_handle_event (GtkEventController *controller,
                           const GdkEvent     *event)
@@ -544,6 +565,12 @@ gtk_gesture_handle_event (GtkEventController *controller,
     case GDK_TOUCH_CANCEL:
       _gtk_gesture_cancel_sequence (gesture, sequence);
       break;
+    case GDK_GRAB_BROKEN:
+      if (!event->grab_broken.grab_window ||
+          !gesture_within_window (gesture, event->grab_broken.grab_window))
+        _gtk_gesture_cancel_all (gesture);
+
+      return FALSE;
     default:
       /* Unhandled event */
       return FALSE;
index 3e8b9c3ec63728fb0c0626679de3f3b1d5ef7722..8d8f1188bd0e71468739b2b09367d2d0f5edf3f8 100644 (file)
@@ -166,6 +166,11 @@ gtk_gesture_single_handle_event (GtkEventController *controller,
         }
 
       break;
+    case GDK_TOUCH_CANCEL:
+    case GDK_GRAB_BROKEN:
+      return GTK_EVENT_CONTROLLER_CLASS (gtk_gesture_single_parent_class)->handle_event (controller,
+                                                                                         event);
+      break;
     default:
       return FALSE;
     }